﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using ChampionsLeagueBets.Domain;
using ChampionsLeagueBets.Infrastructure;
using ChampionsLeagueBets.Web.Mvc.Authentication;
using ChampionsLeagueBets.Web.Mvc.Common;
using SharpArch.NHibernate.Contracts.Repositories;
using MvcContrib;
using SharpArch.NHibernate.Web.Mvc;

namespace ChampionsLeagueBets.Web.Mvc.Controllers
{
	public class GamesController : Controller
	{
		private readonly IExRepository<Game> _gameRepository;
		private readonly IExRepository<Tournament> _tournamentRepository;

		public GamesController(IExRepository<Game> gameRepository, IExRepository<Tournament> tournamentRepository)
		{
			_gameRepository = gameRepository;
			_tournamentRepository = tournamentRepository;
		}

		[HttpPost]
		[Transaction]
		public ActionResult Create(int tourId, Game game)
		{
			if (!RightPrincipal.CurrentUser.IsAdmin) return this.RedirectToAction<HomeController>(c => c.NoRights());

			try
			{
				game.Tournament = _tournamentRepository.Get(tourId);

				if (game.IsValid())
				{
					game = _gameRepository.SaveOrUpdate(game);
				}

				// Dodanie meczu do wszystkich graczy.
				foreach (var tournamentUserResult in game.Tournament.TournamentUserResults)
				{
					GameUserResult gameUserResult = new GameUserResult();
					gameUserResult.CreateDate = DateTime.Now;
					gameUserResult.Game = game;
					gameUserResult.TournamentUserResult = tournamentUserResult;
					tournamentUserResult.GameUserResults.Add(gameUserResult);
				}

				return PartialView("_GamesList", game.Tournament.Games.Where(g => !g.IsDeleted).ToList());
			}
			catch
			{
				return new EmptyResult();
			}
		}

		[HttpPost]
		[Transaction]
		public ActionResult Result(int id, int resultTeamHost, int resultTeamGuest)
		{
			if (!RightPrincipal.CurrentUser.IsAdmin) return this.RedirectToAction<HomeController>(c => c.NoRights());

			try
			{
				Game editable = _gameRepository.Get(id);

				editable.ResultTeamGuest = resultTeamGuest;
				editable.ResultTeamHost = resultTeamHost;
				_gameRepository.SaveOrUpdate(editable);

				RecalculatePoints(editable.Tournament);

				//return this.RedirectToAction<TournamentsController>(a => a.Edit(editable.Tournament.Id));
				return PartialView("_GamesList", editable.Tournament.Games.Where(g => !g.IsDeleted).ToList());
			}
			catch
			{
				return new EmptyResult();
			}
		}

		private void RecalculatePoints(Tournament tournament)
		{
			foreach (var tournamentUserResult in tournament.TournamentUserResults.Where(t => !t.IsDeleted))
			{
				int points = 0;

				foreach (var item in tournamentUserResult.GameUserResults.Where(t => !t.IsDeleted))
				{
					if (item.Game.ResultTeamHost == null || item.Game.ResultTeamGuest == null)
					{
						// Brak wyniku.
					}
					else if(item.ResultTeamHost == null || item.ResultTeamGuest == null)
					{
						// Nie obstawiono zadnego wyniku.
						item.Points = 0;
					}
					else if (item.ResultTeamHost == item.Game.ResultTeamHost && item.ResultTeamGuest == item.Game.ResultTeamGuest)
					{
						// Trafiony wynik
						item.Points = 3;
					}
					else if (item.ResultTeamHost > item.ResultTeamGuest && item.Game.ResultTeamHost > item.Game.ResultTeamGuest)
					{
						// Trafione zwyciestwo gospodarza.
						item.Points = 1;
					}
					else if (item.ResultTeamHost < item.ResultTeamGuest && item.Game.ResultTeamHost < item.Game.ResultTeamGuest)
					{
						// Trafione zwyciestwo gosci.
						item.Points = 1;
					}
					else if (item.ResultTeamHost == item.ResultTeamGuest && item.Game.ResultTeamHost == item.Game.ResultTeamGuest)
					{
						// Trafiony remis.
						item.Points = 1;
					}
					else
					{
						// Nie trafiono.
						item.Points = 0;
					}
					points += item.Points.HasValue ? item.Points.Value : 0;
				}

				tournamentUserResult.Points = points;
				tournamentUserResult.Win = 0;
			}

			// Sortujemy i przeliczamy wygrane kwoty.
			List<TournamentUserResult> winners = tournament.TournamentUserResults.OrderByDescending(o => o.Points).Where(t => !t.IsDeleted).Take(3).ToList();

			int winnerMoney = tournament.Money * tournament.TournamentUserResults.Count;

			if (winners.Count() > 0)
			{
				if (winners.Count() == 1)
				{
					winners[0].Win = winnerMoney;
				}
				else if (winners.Count() == 2)
				{
					winners[0].Win = winnerMoney;
				}
				else
				{
					if (winners[0].Points == winners[1].Points && winners[0].Points == winners[2].Points)
					{
						winners[0].Win = winners[1].Win = winners[2].Win = (int)(winnerMoney * 0.33);
					}
					else if (winners[0].Points == winners[1].Points && winners[1].Points != winners[2].Points)
					{
						winners[0].Win = winners[1].Win = (int)(winnerMoney * 0.35);
						winners[2].Win = (int)(winnerMoney * 0.3);
					}
					else if (winners[0].Points != winners[1].Points && winners[1].Points == winners[2].Points)
					{
						winners[0].Win = (int)(winnerMoney * 0.5);
						winners[1].Win = winners[2].Win = (int)(winnerMoney * 0.25);
					}
					else
					{
						winners[0].Win = (int)(winnerMoney * 0.5);
						winners[1].Win = (int)(winnerMoney * 0.3);
						winners[2].Win = (int)(winnerMoney * 0.2);
					}
				}
			}
		}

		[Transaction]
		public ActionResult Delete(int id)
		{
			if (!RightPrincipal.CurrentUser.IsAdmin) return this.RedirectToAction<HomeController>(c => c.NoRights());

			Game game = _gameRepository.Get(id);
			Tournament tournament = game.Tournament;

			foreach (var gameUserResult in game.GameUserResults)
			{
				gameUserResult.IsDeleted = true;
			}

			_gameRepository.Delete(game);
			_gameRepository.DbContext.CommitTransaction();

			//return this.RedirectToAction<TournamentsController>(c => c.Edit(game.Tournament.Id));
			tournament = _tournamentRepository.Get(tournament.Id);
			return PartialView("_GamesList", tournament.Games.Where(g => !g.IsDeleted).ToList());
		}
	}
}
